package tech.anzhen.simple.rpc.support;

import org.springframework.beans.factory.FactoryBean;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * @author anz
 */
public abstract class RemoteServiceProxyFactorySupport<T> implements FactoryBean<Object> {

    protected Class<T> serviceInterface;

    public void setServiceInterface(Class<T> serviceInterface) {
        this.serviceInterface = serviceInterface;
    }

    @Override
    public Class<?> getObjectType() {
        return serviceInterface;
    }

    @Override
    public boolean isSingleton() {
        return true;
    }

    @Override
    public T getObject() {
        ServiceProxy proxy = new ServiceProxy();
        return (T) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), new Class[]{serviceInterface}, proxy);
    }

    protected abstract T getRemoteProxy();

    class ServiceProxy implements InvocationHandler {

        @Override
        public Object invoke(Object proxy, Method method, Object[] args)
                throws Throwable {
            try {
                Object remoteService = getRemoteProxy();
                return method.invoke(remoteService, args);
            } catch (InvocationTargetException e) {
                throw e.getTargetException();
            }
        }

    }

}
